package com.huaxin.common.message.netnat;

import java.net.InetAddress;

/**
 * Created by hebing on 2016/11/25.
 */

public class NetNatConfig {
    // magic数
    public static final byte[] MAGIC = {0x68, 0x75, 0x61, 0x78, 0x69, 0x6E};// huaxin

    public static final String S_ADDR = "10.0.0.248";// 服务的IP
    public static final int S_PORT = 56571;// 服务的端口
    public static final int C_PORT = 56561;// 本地的端口

    public static final int BUFFSERSIZE = 1500;

    /**
     * 网络数据包类型定义，所有相关的长度范围为1-127
     */
    public static class Type {
        /****************** 服务器相关的消息类型 *********************/
        /**
         * 服务器处理<br>
         * 首次发送至服务器的数据包类型，需附带本地IP以及通话双方的clientID<br>
         * 格式如下：<br>
         * MAGIC<br>
         * + REQUEST<br>
         * + 发送人长度<br>
         * + 接收人长度<br>
         * + 发送人本地IP长度<br>
         * + 发送人<br>
         * + 接收人<br>
         * + 发送人IP
         */
        public static final byte REQUEST = 0x01;

        /**
         * 客户端处理<br>
         * 服务器回执的信息<br>
         * 格式如下：<br>
         * MAGIC<br>
         * + REQUEST_REPLY<br>
         * + 接收人本地IP长度<br>
         * + 接收人外网IP长度<br>
         * + 接收人本地IP<br>
         * + 接收人外网IP
         */
        public static final byte REQUEST_REPLY = 0x02;

        /**
         * 服务器处理<br>
         * NAT穿透失败后，转发数据包<br>
         * 格式如下：<br>
         * MAGIC <br>
         * + FORWARD <br>
         * + 序列号 (Int行，从1开始累积叠加，达到65535后重置为1)<br>
         * + 转发类型（比如音频的数据包类型VOICE_DATA） <br>
         * + 转发的IP个数 <br>
         * + (转发的IP长度 <br>
         * + 转发的IP)（一到多个）<br>
         * + 转发数据长度 (Int类型)<br>
         * + 转发数据<br>
         */
        public static final byte FORWARD = 0x03;

        /**
         * 客户端处理(6 + 1 + 4 + 1)<br>
         * 普通的音频数据包<br>
         * 格式如下<br>
         * MAGIC <br>
         * + VOICE_DATA <br>
         * + 序列号 (Int行，从1开始累积叠加，达到65535后重置为1)<br>
         * + 转发数据长度 <br>
         * + 转发数据<br>
         */
        public static final byte VOICE_DATA = 0x10;
        /**
         * 内/外网客户端处理<br>
         * 内/外网Nat穿透包,点对点时，发送的数据包<br>
         * 格式如下:<br>
         * MAGIC <br>
         * + NAT <br>
         * + 接收人IP长度<br>
         * + 接收人IP<br>
         * <p>
         * 如果收到此类的数据包，则回执给对应的地址即可，这个过程是双向的<br>
         * 校验时发生间隔为100ms<br>
         * 内网的发送次数为5次，校验时间为1000ms<br>
         * 外网的发送次数为10次，校验时间为2000ms<br>
         * 如果超过校验时间，则默认失败；外网的校验次数可能会有多次。
         */
        public static final byte NAT_S = 0x21;
        public static final byte NAT_N = 0x23;
        /**
         * 内/外网客户端处理<br>
         * 内/外网Nat穿透包的回执,点对点时，发送的数据包<br>
         * 格式如下:<br>
         * MAGIC <br>
         * + NAT_REPLY <br>
         * + 回执的IP长度，即NAT类型的接收人的IP长度<br>
         * + 回执的IP，即NAT类型的接收人的IP<br>
         * <p>
         * 如果收到此类的数据包，则说明往此IP发送数据包可用，则后续发送即可
         */
        public static final byte NAT_S_REPLY = 0x22;
        public static final byte NAT_N_REPLY = 0x24;
    }

    public static class NetNatPacket {
        public int size;
        public byte[] data;
        public InetAddress remote;
    }

    public static class NetState {
        public String sender = null; // 发送人
        public String recver = null; // 接收人
        public String senderSIp = null; // 发送人内网IP
        public InetAddress senderNIp = null; // 发送人外网IP
    }

    /**
     * Gets int value
     */
    public static int getInt(byte b) {
        return ((int) b + 256) % 256;
    }

    /**
     * Gets long value
     */
    public static long getLong(byte[] data, int begin, int end) {
        long n = 0;
        for (; begin < end; begin++) {
            n <<= 8;
            n += data[begin] & 0xFF;
        }
        return n;
    }

    /**
     * Sets long value
     */
    public static void setLong(long n, byte[] data, int begin, int end) {
        for (end--; end >= begin; end--) {
            data[end] = (byte) (n % 256);
            n >>= 8;
        }
    }

    /**
     * Gets Int value
     */
    public static int getInt(byte[] data, int begin, int end) {
        return (int) getLong(data, begin, end);
    }

    /**
     * Sets Int value
     */
    public static void setInt(int n, byte[] data, int begin, int end) {
        setLong(n, data, begin, end);
    }
}
